<?php

namespace app\admin\logic\crm;

use app\admin\logic\BaseLogic;
use app\common\model\CrmFieldGroups;
use app\common\model\CrmFieldConfigs;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

/**
 * CRM设置逻辑层
 * 用于处理客户资料分组和字段配置的业务逻辑
 */
class CrmSettingsLogic extends BaseLogic
{
    public function __construct()
    {
        $this->model = new CrmFieldGroups();
    }
    /**
     * 搜索分组
     * @param array $where
     * @return \think\db\Query
     */
    public function searchGroups(array $where = [])
    {
        $model = CrmFieldGroups::where([]);

        if (!empty($where['name'])) {
            $model->where('name', 'like', '%' . $where['name'] . '%');
        }

        if (!empty($where['code'])) {
            $model->where('code', 'like', '%' . $where['code'] . '%');
        }

        if (isset($where['status']) && $where['status'] !== '') {
            $model->where('status', $where['status']);
        }

        if (!empty($where['create_time'])) {
            $model->whereTime('create_time', 'between', $where['create_time']);
        }

        return $model;
    }

    /**
     * 根据ID获取分组
     * @param int $id
     * @return array|null
     */
    public function getGroupById(int $id)
    {
        try {
            $group = CrmFieldGroups::find($id);
            return $group ? $group->toArray() : null;
        } catch (DataNotFoundException | ModelNotFoundException | DbException $e) {
            return null;
        }
    }

    /**
     * 检查分组编码是否存在
     * @param string $code
     * @param int $excludeId
     * @return bool
     */
    public function checkGroupCodeExists(string $code, int $excludeId = 0): bool
    {
        $query = CrmFieldGroups::where('code', $code);
        if ($excludeId > 0) {
            $query->where('id', '<>', $excludeId);
        }
        return $query->count() > 0;
    }

    /**
     * 保存分组
     * @param array $data
     * @return array|false
     */
    public function saveGroup(array $data)
    {
        try {
            $group = new CrmFieldGroups();
            $group->name = $data['name'];
            $group->code = $data['code'];
            $group->sort = $data['sort'] ?? 0;
            $group->icon = $data['icon'] ?? null;
            $group->color = $data['color'] ?? null;
            
            if ($group->save()) {
                return $group->toArray();
            }
            return false;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 更新分组
     * @param int $id
     * @param array $data
     * @return array|false
     */
    public function updateGroup(int $id, array $data)
    {
        try {
            $group = CrmFieldGroups::find($id);
            if (!$group) {
                return false;
            }

            $group->name = $data['name'];
            $group->code = $data['code'];
            $group->sort = $data['sort'] ?? 0;
            $group->icon = $data['icon'] ?? null;
            $group->color = $data['color'] ?? null;
            
            if ($group->save()) {
                return $group->toArray();
            }
            return false;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 删除分组
     * @param int $id
     * @return bool
     */
    public function deleteGroup(int $id): bool
    {
        try {
            $group = CrmFieldGroups::find($id);
            if (!$group) {
                return false;
            }

            return $group->delete() !== false;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 检查分组下是否有字段
     * @param int $groupId
     * @return bool
     */
    public function hasFieldsInGroup(int $groupId): bool
    {
        return CrmFieldConfigs::where('group_id', $groupId)->count() > 0;
    }

    /**
     * 搜索字段
     * @param array $where
     * @return \think\db\Query
     */
    public function searchFields(array $where = [])
    {
        $model = CrmFieldConfigs::where([]);

        if (!empty($where['group_id'])) {
            $model->where('group_id', $where['group_id']);
        }

        if (!empty($where['name'])) {
            $model->where('name', 'like', '%' . $where['name'] . '%');
        }

        if (!empty($where['label'])) {
            $model->where('label', 'like', '%' . $where['label'] . '%');
        }

        if (!empty($where['type'])) {
            $model->where('type', $where['type']);
        }

        if (!empty($where['create_time'])) {
            $model->whereTime('create_time', 'between', $where['create_time']);
        }

        return $model;
    }

    /**
     * 根据ID获取字段
     * @param int $id
     * @return array|null
     */
    public function getFieldById(int $id)
    {
        try {
            $field = CrmFieldConfigs::with(['group'])->find($id);
            if ($field) {
                $data = $field->toArray();
                // 确保选项是数组格式
                if (!empty($data['options']) && is_string($data['options'])) {
                    $data['options'] = json_decode($data['options'], true);
                }
                return $data;
            }
            return null;
        } catch (DataNotFoundException | ModelNotFoundException | DbException $e) {
            return null;
        }
    }

    /**
     * 检查字段名称是否存在
     * @param string $name
     * @param int $excludeId
     * @return bool
     */
    public function checkFieldNameExists(string $name, int $excludeId = 0): bool
    {
        $query = CrmFieldConfigs::where('name', $name);
        if ($excludeId > 0) {
            $query->where('id', '<>', $excludeId);
        }
        return $query->count() > 0;
    }

    /**
     * 保存字段
     * @param array $data
     * @return array|false
     */
    public function saveField(array $data)
    {
        try {
            $field = new CrmFieldConfigs();
            $field->group_id = $data['group_id'];
            $field->name = $data['name'];
            $field->placeholder = $data['placeholder'];
            $field->label = $data['label'];
            $field->type = $data['type'];
            $field->required = $data['required'] ?? 0;
            $field->sort = $data['sort'] ?? 0;
            $field->max_length = $data['max_length'] ?? 0;
            $field->validation = $data['validation'] ?? null;
            
            // 处理选项数据
            if (in_array($data['type'], ['select', 'radio', 'checkbox']) && !empty($data['options'])) {
                $field->options = is_array($data['options']) ? json_encode($data['options']) : $data['options'];
            } else {
                $field->options = null;
            }
            
            if ($field->save()) {
                return $field->toArray();
            }
            return false;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 更新字段
     * @param int $id
     * @param array $data
     * @return array|false
     */
    public function updateField(int $id, array $data)
    {
        try {
            $field = CrmFieldConfigs::find($id);
            if (!$field) {
                return false;
            }

            $field->group_id = $data['group_id'];
            $field->name = $data['name'];
            $field->placeholder = $data['placeholder'];
            $field->label = $data['label'];
            $field->type = $data['type'];
            $field->required = $data['required'] ?? 0;
            $field->sort = $data['sort'] ?? 0;
            $field->max_length = $data['max_length'] ?? 0;
            $field->validation = $data['validation'] ?? null;
            
            // 处理选项数据
            if (in_array($data['type'], ['select', 'radio', 'checkbox']) && !empty($data['options'])) {
                $field->options = is_array($data['options']) ? json_encode($data['options']) : $data['options'];
            } else {
                $field->options = null;
            }
            
            if ($field->save()) {
                return $field->toArray();
            }
            return false;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 删除字段
     * @param int $id
     * @return bool
     */
    public function deleteField(int $id): bool
    {
        try {
            $field = CrmFieldConfigs::find($id);
            if (!$field) {
                return false;
            }

            return $field->delete() !== false;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 获取分组及其字段的树形结构
     * @return array
     */
    public function getGroupsWithFields(): array
    {
        try {
            $groups = CrmFieldGroups::order('sort asc, id asc')->field('id, name, code, icon, sort')->select();

            $result = [];
            foreach ($groups as $group) {
                $fields = CrmFieldConfigs::where('group_id', $group['id'])->field('id, group_id, name, placeholder, label, type, required, sort, max_length, validation, options, show_front_list, user_fill')->order('group_id asc, sort asc, id asc')->select();

                // 处理字段的选项数据
                foreach ($fields as &$field) {
                    if (!empty($field['options']) && is_string($field['options'])) {
                        $field['options'] = json_decode($field['options'], true);
                    }
                }
                $group['fields'] = $fields;
                $result[] = $group;
            }

            return $result;
        } catch (\Exception $e) {
            return [];
        }
    }

    /**
     * 保存完整的分组和字段配置
     * @param array $groupsData 包含分组和字段的完整数据结构
     * @return bool
     */
    public function saveCrmSetting(array $groupsData): bool
    {
        // 开始事务
        $db = $this->model;
        $db->startTrans();
        try {
            // 获取现有分组和字段的ID列表
            $existingGroupIds = CrmFieldGroups::column('id');
            $existingFieldIds = CrmFieldConfigs::column('id');
            $newGroupIds = [];
            $newFieldIds = [];

            // 处理每个分组
            foreach ($groupsData as $groupData) {
                // 处理分组
                $groupId = $this->processGroup($groupData, $existingGroupIds);
                if ($groupId === false) {
                    throw new \Exception('保存分组失败');
                }
                $newGroupIds[] = $groupId;
                
                // 处理该分组下的字段
                if (!empty($groupData['fields']) && is_array($groupData['fields'])) {
                    foreach ($groupData['fields'] as $fieldData) {
                        $fieldData['group_id'] = $groupId; // 确保字段属于正确的分组
                        $fieldId = $this->processField($fieldData, $existingFieldIds);
                        if ($fieldId === false) {
                            throw new \Exception('保存字段失败');
                        }
                        $newFieldIds[] = $fieldId;
                    }
                }
            }
                
            // 删除不再存在的分组（如果分组下没有字段）
            $groupsToDelete = array_diff($existingGroupIds, $newGroupIds);
            foreach ($groupsToDelete as $groupId) {
                if (!$this->hasFieldsInGroup($groupId)) {
                    $this->deleteGroup($groupId);
                }
            }

            // 删除不再存在的字段
            $fieldsToDelete = array_diff($existingFieldIds, $newFieldIds);
            foreach ($fieldsToDelete as $fieldId) {
                $this->deleteField($fieldId);
            }

            $db->commit();
            return true;
        } catch (\Exception $e) {
            $db->rollback();
            throw new \Exception('保存CRM设置失败: ' . $e->getMessage());
        }
    }

    /**
     * 处理单个分组
     * @param array $groupData
     * @param array $existingGroupIds
     * @return int|false
     */
    protected function processGroup(array $groupData, array $existingGroupIds)
    {
        $groupInfo = [
            'name' => trim($groupData['name'] ?? ''),
            'code' => trim($groupData['code'] ?? ''),
            'sort' => intval($groupData['sort'] ?? 0),
            'icon' => trim($groupData['icon'] ?? ''),
            'color' => trim($groupData['color'] ?? ''),
        ];

        $groupId = $groupData['id'] ?? 0;
   
        // 只保留业务逻辑验证（唯一性检查）
        if ($this->checkGroupCodeExists($groupInfo['code'], $groupId)) {
            throw new \Exception('分组编码已存在: ' . $groupInfo['code']);
        }

        if ($groupId > 0 && in_array($groupId, $existingGroupIds)) {
            // 更新现有分组
            $result = $this->updateGroup($groupId, $groupInfo);
            if (!$result) {
                throw new \Exception('更新分组失败: ' . $groupInfo['name']);
            }
            return $groupId;
        } else {
            // 创建新分组
            $result = $this->saveGroup($groupInfo);
            if (!$result) {
                throw new \Exception('创建分组失败: ' . $groupInfo['name']);
            }
            return $result['id'];
        }
    }

    /**
     * 处理单个字段
     * @param array $fieldData
     * @param array $existingFieldIds
     * @return int|false
     */
    protected function processField(array $fieldData, array $existingFieldIds)
    {
        $fieldInfo = [
            'name' => trim($fieldData['name'] ?? ''),
            'label' => trim($fieldData['label'] ?? ''),
            'type' => trim($fieldData['type'] ?? 'text'),
            'placeholder' => trim($fieldData['placeholder'] ?? ''),
            'group_id' => intval($fieldData['group_id'] ?? 0),
            'required' => intval($fieldData['required'] ?? 0),
            'sort' => intval($fieldData['sort'] ?? 0),
            'max_length' => intval($fieldData['max_length'] ?? 0),
            'validation' => trim($fieldData['validation'] ?? ''),
        ];

        $fieldId = $fieldData['id'] ?? 0;
        // 检查字段名称是否已存在
        if ($this->checkFieldNameExists($fieldInfo['name'], $fieldId)) {
            throw new \Exception('字段名称已存在: ' . $fieldInfo['name']);
        }

        // 处理选项数据（仅针对需要选项的字段类型）
        $needOptionsTypes = ['select', 'radio', 'checkbox'];
        if (in_array($fieldInfo['type'], $needOptionsTypes)) {
            if (empty($fieldData['options'])) {
                throw new \Exception('该字段类型必须提供选项数据');
            } else {
                if (is_string($fieldData['options'])) {
                    $fieldData['options'] = json_decode($fieldData['options'], true);
                }
                if (!is_array($fieldData['options'])) {
                    throw new \Exception('选项数据格式错误');
                }
            }
            
            // 验证选项格式
            foreach ($fieldData['options'] as $option) {
                if (!is_array($option) || !isset($option['value'], $option['label'])) {
                    throw new \Exception('选项格式不正确，必须包含value和label字段');
                }
            }
            
            $fieldInfo['options'] = json_encode($fieldData['options']);
        } else {
            $fieldInfo['options'] = null;
        }

        if ($fieldId > 0 && in_array($fieldId, $existingFieldIds)) {
            // 更新现有字段
            $result = $this->updateField($fieldId, $fieldInfo);
            if (!$result) {
                throw new \Exception('更新字段失败: ' . $fieldInfo['label']);
            }
            return $fieldId;
        } else {
            // 创建新字段
            $result = $this->saveField($fieldInfo);
            if (!$result) {
                throw new \Exception('创建字段失败: ' . $fieldInfo['label']);
            }
            return $result['id'];
        }
    }
}